from logging import getLogger
from pprint import pformat
from typing import Any, Dict

from common.event_queue import IAgentEventPublisher
from common.types import AgentID, Event
from common.utils.code_utils import del_key
from infection_monkey.i_puppet import ExploiterResult, TargetHost

from .zerologon import ZerologonExploiter
from .zerologon_options import ZerologonOptions

logger = getLogger(__name__)


class Plugin:
    def __init__(
        self,
        *,
        plugin_name: str,
        agent_id: AgentID,
        agent_event_publisher: IAgentEventPublisher,
        **kwargs,
    ):
        self._plugin_name = plugin_name
        self._agent_id = agent_id
        self._agent_event_publisher = agent_event_publisher

    def run(
        self,
        *,
        host: TargetHost,
        options: Dict[str, Any],
        interrupt: Event,
        **kwargs,
    ) -> ExploiterResult:
        # HTTP ports options are hack because they are needed in fingerprinters
        del_key(options, "http_ports")

        try:
            logger.debug(f"Parsing options: {pformat(options)}")
            zerologon_options = ZerologonOptions(**options)
        except Exception as err:
            msg = f"Failed to parse Zerologon options: {err}"
            logger.exception(msg)
            return ExploiterResult(error_message=msg)

        try:
            logger.debug(f"Running Zerologon exploiter on host {host.ip}")
            exploiter = ZerologonExploiter()
            return exploiter.exploit_host(
                self._agent_id, host, self._agent_event_publisher, zerologon_options, interrupt
            )
        except Exception as err:
            msg = f"An unexpected exception occurred while attempting to exploit host: {err}"
            logger.exception(msg)
            return ExploiterResult(error_message=msg)
